package com.itlong.cloud.sdk.service.impl;

import com.google.zxing.BarcodeFormat;
import com.itlong.cloud.POJO.DTO.property.PropertyAddVisitorDTO;
import com.itlong.cloud.POJO.DTO.sdk.CloudDeviceSDKDTO;
import com.itlong.cloud.POJO.DTO.sdk.CloudTalkSDKServerVisitorPwdDTO;
import com.itlong.cloud.POJO.PO.AppVisitorPassCodeRecordPO;
import com.itlong.cloud.POJO.PO.PropertyRoleProjectPO;
import com.itlong.cloud.POJO.PO.PropertyUserInfoPO;
import com.itlong.cloud.POJO.VO.sdk.CloudTalkSDKServerUserCacheVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.IPropertyVisitorPassCodeRecordDao;
import com.itlong.cloud.sdk.dao.ICloudTalkSDKServerUserDao;
import com.itlong.cloud.sdk.dao.ISDKServerOldPropertyUserDao;
import com.itlong.cloud.sdk.service.ICloudTalkSDKServerUserService;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.picture.QrcodeUtils;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.random.RandomUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchProviderException;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * <desc>
 * 云对讲sdk人员服务层接口
 * </desc>
 *
 * @createDate 2018/05/11
 */

@Service
@RefreshScope
public class CloudTalkSDKServerUserServiceImpl implements ICloudTalkSDKServerUserService {

    private static final Logger LOG = LoggerFactory.getLogger(CloudTalkSDKServerUserServiceImpl.class);

    @Autowired
    ICloudTalkSDKServerUserDao iCloudTalkSDKServerUserDao;

    @Value("${" + PlatformConstants.PROPERTY_USER_DEFAULT_PASSWORD + "}")
    String userDefaultPassword;

    @Value("${" + PlatformConstants.CLOUDTALK_SDK_USER_TOKEN_KEY + "}")
    String CLOUDTALK_SDK_SERVER_USER_TOKEN_KEY;

    @Value("${" + PlatformConstants.CLOUDTALK_SDK_APP_TOKEN_KEY + "}")
    String CLOUDTALK_SDK_APP_TOKEN_KEY;

    @Autowired
    ISDKServerOldPropertyUserDao isdkUserDao;

    @Autowired
    IPropertyVisitorPassCodeRecordDao iPropertyVisitorPassCodeRecordDao;
    @Autowired
    private RedisService redisServiceObject;
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Lock writeLock;
    @PostConstruct
    public void init(){
        writeLock = lock.writeLock();
    }

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;

    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;

    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;

    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;

    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;

    //Redis工具接口类
    @Autowired
    private RedisService<CloudTalkSDKServerUserCacheVO> redisService;


    /**
     * <desc>
     * 申请开发者账号
     * <desc/>
     *
     * @param userName     开发者账号名称
     * @param desProjectId 项目编号
     * @return
     * @author JuGuang.S
     * @createDate 2018/05/11
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public PropertyUserInfoPO applicationAccount(String userName, String desProjectId) throws Exception {
        //1.保存物业账号基础信息（property_user_info）
        String userId = LogicIdUtil.bussinessId();
        PropertyUserInfoPO userInfoPO = new PropertyUserInfoPO();
        userInfoPO.setUserId(userId);
        userInfoPO.setRoleId(PropertyPublicRoleEnum.DEVELOPER.getRoleId());
        userInfoPO.setPassword(Md5EncryptUtil.md5(userDefaultPassword));
        userInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
        userInfoPO.setAppsecret(LogicIdUtil.getProjectKey());
        userInfoPO.setUserName(userName);
        userInfoPO.setCreateTime(new Date());
        Map<String, Object> params = SqlUtil.durableData(userInfoPO, PlatformConstants.TABLE_SAVE);
        iCloudTalkSDKServerUserDao.save(params);

        //2.保存用户_角色_项目关系（property_role_project）
        List<PropertyRoleProjectPO> roleProjectPOS = new ArrayList<>();
        PropertyRoleProjectPO roleProjectPO = new PropertyRoleProjectPO();
        roleProjectPO.setProjectId(desProjectId);
        roleProjectPO.setRoleId(PropertyPublicRoleEnum.DEVELOPER.getRoleId());
        roleProjectPO.setUserId(userId);
        roleProjectPOS.add(roleProjectPO);
        iCloudTalkSDKServerUserDao.saveRoleProject(roleProjectPOS);

        return userInfoPO;

    }

    /**
     * <desc>
     *      根据Appsecret查找物业账号用户
     * <desc/>
     * @param   appsecret   密钥
     * @param   desProjectId   项目编号
     *@return
     * @author JuGuang.S
     * @createDate 2018/05/11
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public PropertyUserInfoPO getPropertyUserByAppsecret(String appsecret,String desProjectId) throws Exception {
        PropertyUserInfoPO userInfoPO = iCloudTalkSDKServerUserDao.getPropertyUserByAppsecret(appsecret);

        //2.保存用户_角色_项目关系（property_role_project）
        List<PropertyRoleProjectPO> roleProjectPOS = new ArrayList<>();
        PropertyRoleProjectPO roleProjectPO = new PropertyRoleProjectPO();
        roleProjectPO.setProjectId(desProjectId);
        roleProjectPO.setRoleId(PropertyPublicRoleEnum.DEVELOPER.getRoleId());
        roleProjectPO.setUserId(userInfoPO.getUserId());
        roleProjectPOS.add(roleProjectPO);
        iCloudTalkSDKServerUserDao.saveRoleProject(roleProjectPOS);

        return userInfoPO;

    }

    /**
     * <desc>
     *      云对讲SDK服务端认证登录
     * <desc/>
     * @param appId     应用接入凭证
     * @param appsecret 应用接入密钥
     * @return  缓存对象
     * @author JuGuang.S
     * @createDate 2018/05/15
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer sdkServerLogin(String appId, String appsecret) {
        if (StringUtils.isNotEmpty(appId) && StringUtils.isNotEmpty(appsecret)) {
            //数据库校验appid和appsecret
            Map<String, Object> params = new HashMap<>();
            params.put("userId", appId);
            params.put("appsecret", appsecret);
            params.put("status", DataStatusEnum.NORMAL.getType());
            List<PropertyUserInfoPO> userPOs = isdkUserDao.getUserByParams(params);
            if (userPOs != null && !userPOs.isEmpty()) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * <desc>
     *      云电梯SDK判断机器人是否有权限
     * <desc/>
     * @param appId     应用接入凭证
     * @param appsecret 应用接入密钥
     * @param robotId 机器人编号
     * @return
     * @author Qiang.S
     * @createDate 2019/01/03
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer checkRobot(String appId, String appsecret, String robotId) {
            //数据库校验appid和appsecret
            Map<String, Object> params = new HashMap<>();
            params.put("userId", appId);
            params.put("appsecret", appsecret);
            params.put("robotId", robotId);
            params.put("status", DataStatusEnum.NORMAL.getType());
        return isdkUserDao.checkRobot(params);
    }

    /**
     * <desc>
     *      云电梯SDK判断机器人是否有权限
     * <desc/>
     * @param dto
     * @return
     * @author Qiang.S
     * @createDate 2020/03/23
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer checkRobotNew(CloudDeviceSDKDTO dto) {
        int count = 0;
        //数据库校验appid和appsecret
        Map<String, Object> params = new HashMap<>();
        params.put("userId", dto.getAppId());
        params.put("appsecret", dto.getAppSecret());
        params.put("robotId", dto.getRobotId());
        params.put("status", DataStatusEnum.NORMAL.getType());
        params.put("projectId",dto.getProjectId());
        params.put("deviceType",dto.getRobotDevelopDeviceType());
        if ("4".equals(dto.getRoleId())) {//独立开发者
            count = isdkUserDao.checkRobot(params);
        } else if ("7".equals(dto.getRoleId())) {//机器人开发者
            count = isdkUserDao.checkRobotDevelopRobot(params);
        }
        return count;
    }

    /**
     * <desc>
     *      从缓存中获取appid
     * </desc>
     *
     * @param token 用户token
     * @param tokenType 1代表APP开门音视频切换的token 2代表除此之外的token
     * @return
     * @author Jiaqi.X
     * @createDate 2018/05/17
     */
    @Override
    public CloudTalkSDKServerUserCacheVO retrieve(String token,String tokenType) {
        try {
            if (StringUtils.isBlank(token)) {
                return null;
            }
            //解密拿到appId
            if(tokenType.equals("2")){
                String appId = UserTokenUtil.tokenDecrypt(token, CLOUDTALK_SDK_SERVER_USER_TOKEN_KEY);
                return redisService.getObject(String.format("%s%s", RedisConstant.CLOUD_TALK_SDK_USER_REDIS_KEY, appId),CloudTalkSDKServerUserCacheVO.class);
            }
            if(tokenType.equals("1")){
                String appId = UserTokenUtil.tokenDecrypt(token, CLOUDTALK_SDK_APP_TOKEN_KEY);
                return redisService.getObject(String.format("%s%s", RedisConstant.CLOUD_TALK_SDK_APP_REDIS_KEY, appId),CloudTalkSDKServerUserCacheVO.class);
            }
            return null;
        }catch (RedisConnectionFailureException e){
            throw new DataAccessException("云对讲SDKretrieve【从缓存中获取用户信息】redis连接失败") ;
        }
    }

    /**
     * <desc>
     *      根据appId获取该应用下所关联的项目信息
     * </desc>
     *
     * @param appId 应用Id
     * @return
     * @author Juguang.S
     * @createDate 2018/12/21
     */
    @Override
    public List<String> getProjectIdByParams(String appId) {
        return iCloudTalkSDKServerUserDao.getProjectIdByParams(appId);
    }

    /**
     * <desc>
     *      云对讲SDK APP端认证登录
     * <desc/>
     * @param appId     应用接入凭证
     * @param appsecret 应用接入密钥
     * @return  缓存对象
     * @author JuGuang.S
     * @createDate 2018/11/21
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public CloudTalkSDKServerUserCacheVO sdkAppLogin(String appId, String appsecret) {
        try {
            if (StringUtils.isNotEmpty(appId) && StringUtils.isNotEmpty(appsecret)) {
                //数据库校验appid和appsecret
                Map<String, Object> params = new HashMap<>();
                params.put("userId", appId);
                params.put("appsecret", appsecret);
                params.put("status", DataStatusEnum.NORMAL.getType());
                List<PropertyUserInfoPO> userPOs = isdkUserDao.getUserByParams(params);
                List<String> projectIdList = iCloudTalkSDKServerUserDao.getProjectIdByParams(appId);
                String projectStr = null;
                if(!projectIdList.isEmpty() && projectIdList!=null){
                    projectStr = String.join(",",projectIdList);
                }
                if (userPOs != null && !userPOs.isEmpty()) {
                    //更新redis缓存，清空旧的缓存,缓存中只保存appid
                    String redisKey = String.format("%s%s", RedisConstant.CLOUD_TALK_SDK_APP_REDIS_KEY, appId);
                    String token = UserTokenUtil.tokenEncrypt(appId, CLOUDTALK_SDK_APP_TOKEN_KEY, SystemTypeEnum.CLOUD_TALK_SDK_SERVER.getType());
                    CloudTalkSDKServerUserCacheVO userCache = new CloudTalkSDKServerUserCacheVO(appId,projectStr,token);
                    redisService.set(redisKey, RedisConstant.CLOUD_TALK_SDK_USER_LOGIN_TIME, userCache);

                    return userCache;
                }
            }
            return null;
        } catch (UnsupportedEncodingException e) {
            throw new DataAccessException("【云对讲SDK App认证_CloudTalkSDKServerUserServiceImpl_sdkAppLogin】处理异常", e);
        }
    }

    /**
     * <desc>
     *      云对讲SDK 生成访客动态密码
     * <desc/>
     * @param visitorPwdDTO     生成访客动态密码的信息
     * @return
     * @author JuGuang.S
     * @createDate 2018/11/24
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public AppVisitorPassCodeRecordPO getVisitorPwdAndQrCode(CloudTalkSDKServerVisitorPwdDTO visitorPwdDTO) throws Exception {

        //如果次数为空或者大于10 默认为10
        if(StringUtils.isBlank(visitorPwdDTO.getCountLimit())){
            visitorPwdDTO.setCountLimit("10");
        }
        //根据buildNum unitNum获取buildId unitId
        Map<String,String> map = iPropertyVisitorPassCodeRecordDao.getBuildInfo(visitorPwdDTO.getProjectId(),visitorPwdDTO.getBuildNum(),visitorPwdDTO.getUnitNum());
        AppVisitorPassCodeRecordPO passPO=new AppVisitorPassCodeRecordPO();
        passPO.setBuildId(map.get("buildId"));
        passPO.setUnitId(map.get("unitId"));
        passPO.setCreateTime(new Date());
        passPO.setSource(3);
        //如果有效时间为空，默认为当前创建时间
        if(StringUtils.isBlank(visitorPwdDTO.getEffectiveTime())){
            visitorPwdDTO.setEffectiveTime("1440");
        }
        passPO.setStartTime(passPO.getCreateTime());
        passPO.setPassId(LogicIdUtil.bussinessId());
        passPO.setVisitorName(visitorPwdDTO.getVisitorName());
        passPO.setVisitorPhone(visitorPwdDTO.getVisitorPhone());
        passPO.setStatus(DataStatusEnum.NORMAL.getType());
        passPO.setUserId(visitorPwdDTO.getUserId());
        passPO.setFloorNum(visitorPwdDTO.getFloorNum());
        PropertyAddVisitorDTO AddVisitorDTO = new PropertyAddVisitorDTO();
        AddVisitorDTO.setBuildId(map.get("buildId"));
        AddVisitorDTO.setUnitId(map.get("unitId"));
        AddVisitorDTO.setProjectId(visitorPwdDTO.getProjectId());
        //云对讲机号 多个，号分隔
        Map<String,Object> cloudTalkMap=iPropertyVisitorPassCodeRecordDao.getCloudIntercomUniquesByBuildIdAndUnitId(AddVisitorDTO);
        String cloudUniques = cloudTalkMap!=null?cloudTalkMap.get("deviceIds").toString():null;
        //门禁机号 多个，号分隔
        Map<String,Object> entranceMap=iPropertyVisitorPassCodeRecordDao.getEntranceUniquesByBuildIdAndUnitId(AddVisitorDTO);
        String entranceUniques = entranceMap!=null?entranceMap.get("deviceIds").toString():null;
        //电梯机号 多个，号分隔
        String elevatorUniques=iPropertyVisitorPassCodeRecordDao.getElevatorUniquesByBuildIdAndUnitId(AddVisitorDTO);
        //获取房间号的楼栋信息
        //如果没有设备权限直接返回null
        if(StringUtils.isNotBlank(cloudUniques) || StringUtils.isNotBlank(entranceUniques) || StringUtils.isNotBlank(elevatorUniques)) {
            String uniques = StringUtils.isNotBlank(cloudUniques) ? cloudUniques + "," : "";
            uniques += StringUtils.isNotBlank(entranceUniques) ? uniques + entranceUniques  : uniques;
            //为了防止门禁与云对讲机号重复，现对设备机号进行去重处理
            String[] allDeviceIds = StringHandlerUtil.splitString(uniques);
            Set<String> setDeviceIds = new HashSet<>();
            String deviceIds = "";
            for (String deviceId : allDeviceIds) {
                if (!deviceId.equals("null") && setDeviceIds.add(deviceId)) {
                    deviceIds += StringHandlerUtil.autlSupply(4,deviceId,"0") + ",";
                }
            }
            //设置门禁的id
            passPO.setDeviceId(StringUtils.isNotBlank(deviceIds) ? deviceIds.substring(0, deviceIds.length() - 1) : "");
            passPO.setUseNum(0);
            //生成二维码信息
            Map<String,Object> codeResult;
            codeResult = this.getQrCode(elevatorUniques, deviceIds, visitorPwdDTO.getProjectId(), DateUtil.fomatDate(passPO.getStartTime()),
                    visitorPwdDTO.getUserId(), visitorPwdDTO.getVisitorPhone(),Integer.valueOf(visitorPwdDTO.getEffectiveTime()),
                    visitorPwdDTO.getFloorNum());
            passPO.setFloorNum(visitorPwdDTO.getFloorNum());
            passPO.setQrcode(codeResult.get("qrcode").toString().toUpperCase());
        }else{
            passPO.setQrcode("00000000000000000000000000000000000000000000000000");
        }
        //生成二维码图片
        BufferedImage bim = QrcodeUtils.getQR_CODEBufferedImage(passPO.getQrcode(), BarcodeFormat.QR_CODE, 300, 300, QrcodeUtils.getDecodeHintType());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(bim,"png",out);
        InputStream input = new ByteArrayInputStream(out.toByteArray());
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                input,
                "png",
                FILE_ACCESS_URL,
                FileCatalogEnum.VISITOR_PASS_QRCODE_FILE.getType()
        );
        Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
        Boolean returnCode = (Boolean)resultMap.get("returnCode");
        if (returnCode == true){
            passPO.setQrcodeUrl(resultMap.get("accessPath").toString());
        }
        passPO.setProjectId(visitorPwdDTO.getProjectId());
        //设置有效结束时间
        passPO.setEndTime(DateUtil.addCurrentTime(passPO.getStartTime(),
                Integer.valueOf(visitorPwdDTO.getEffectiveTime()) * 60 * 1000));
        passPO.setNum(Integer.valueOf(visitorPwdDTO.getCountLimit()));
        passPO.setSource(VisitorSourceTypeEnum.PROPERTY.getType());
        //判断项目配置信息 生成动态密码 0在线版 1离线版
        if(visitorPwdDTO.getViladType().equals("1")) {
            //在线版验证方式
            String random = StringHandlerUtil.autlSupply(4, RandomUtil.getRandomAround(9999, 0).toString(), "0");
            int repeat = 1;
            try {
                //获取写锁
                writeLock.lock();
                while (repeat > 0) {
                    //检查是否重复
                    repeat = iPropertyVisitorPassCodeRecordDao.checkRepeatPassword(random,
                            DateUtil.fomatDate(passPO.getStartTime(), DateUtil.YYYYMMDDHHMM),
                            DateUtil.fomatDate(passPO.getEndTime(), DateUtil.YYYYMMDDHHMM));
                    if (repeat > 0) {
                        random = StringHandlerUtil.autlSupply(4, RandomUtil.getRandomAround(9999, 0).toString(), "0");
                    }
                }
                passPO.setPassword(random);
            } catch (Exception e) {
                throw e;
            } finally {
                writeLock.unlock();
            }
            passPO.setType(DynamicPasswordTypeEnum.ONLINE.getType());
        }else{
            //脱机版验证方式
            //获取加密后的项目秘钥
            String encriptProjKey=StringHandlerUtil.bytesToHexStr(DesEncryptUtil.getQrcodeKey(DesEncryptUtil.QRCODE_INIT_KEY, visitorPwdDTO.getProjectId()));
            //动态密码规则 楼层（03）+权限组号（01）+四位密码
            StringBuilder password = new StringBuilder(StringHandlerUtil.autlSupply(2,((Integer)Math.abs(Integer.valueOf(visitorPwdDTO.getFloorNum()))).toString(),"0"));
            //获取权限组号
            String unitGroupNum = iPropertyVisitorPassCodeRecordDao.getGroupNumByUnitId(map.get("unitId"));
            if(StringUtils.isNotBlank(unitGroupNum) && Integer.valueOf(unitGroupNum) <= 99){
                password.append(unitGroupNum);
            }else{
                password.append("00");
            }
            StringBuilder encriptValue = new StringBuilder(password.toString());
            encriptValue.append(DateUtil.fomatDate(passPO.getEndTime(),"yyMMdd"));
            //获取时间段
            List<String> times = DateUtil.getIntervalTimeList("00:00:00","23:59:59",30);
            for(Integer i = 0 ; i<times.size() ; i++){
                if(i == times.size() -1 ){
                    encriptValue.append("48");
                    break;
                }else if(DateUtil.formatStringToDate(times.get(i),"HH:mm:ss").getTime() <=
                        DateUtil.formatStringToDate(DateUtil.fomatDate(passPO.getEndTime(),"HH:mm:ss"),"HH:mm:ss").getTime()
                        && DateUtil.formatStringToDate(times.get(i+1),"HH:mm:ss").getTime() >=
                        DateUtil.formatStringToDate(DateUtil.fomatDate(passPO.getEndTime(),"HH:mm:ss"),"HH:mm:ss").getTime() ){
                    encriptValue.append(StringHandlerUtil.autlSupply(2,i.toString(),"0"));
                    break;
                }
            }
            //备用字节
            encriptValue.append("0000");
            String des = DesEncryptUtil.getUserKey(encriptValue.toString(),encriptProjKey);
            String hex = des.substring(des.length()-6,des.length());
            hex=((Integer)Integer.parseInt(hex,16)).toString();
            password.append(hex.substring(hex.length()-4,hex.length()));
            passPO.setPassword(password.toString());
            passPO.setType(DynamicPasswordTypeEnum.OFFLINE.getType());
        }
        iPropertyVisitorPassCodeRecordDao.save(SqlUtil.durableData(passPO, PlatformConstants.TABLE_SAVE));
        return passPO;
    }

    /**
     * <desc>
     *      校验buildNum unitNum 该项目下是否有该单元信息
     * <desc/>
     * @param visitorPwdDTO     生成访客动态密码的信息
     * @return
     * @author JuGuang.S
     * @createDate 2018/11/24
     */
    @Override
    public Map<String, String> getExistBuildInfo(CloudTalkSDKServerVisitorPwdDTO visitorPwdDTO) {
        return iPropertyVisitorPassCodeRecordDao.getBuildInfo(visitorPwdDTO.getProjectId(),visitorPwdDTO.getBuildNum(),visitorPwdDTO.getUnitNum());
    }

    /**
     * <desc>
     *      根据ProjectId,buildNum查询出该楼栋的最高楼层
     * <desc/>
     * @param
     * @return
     * @author JuGuang.S
     * @createDate 2018/12/14
     */
    @Override
    public Integer getBuildFloorNum(String projectId, String buildNum) {
        return isdkUserDao.getBuildFloorNum(projectId,buildNum);
    }

    /**
     * <desc>
     *      生成访客通行二维码
     * </desc>
     *
     * @param doorIds 门禁id（机号） 多个,号分隔
     * @param projectId 项目id
     * @param userId 用户id
     * @param phoneNum 当前用户手机号
     * @return
     */
    private Map<String,Object> getQrCode(String elevatorUniques,String doorIds,String projectId,
                                         String startTime,String userId,String phoneNum,Integer timeLimit,String floorNum) throws NoSuchProviderException, ParseException {
        Map<String,Object> result = new HashMap<>();
        //开始拼接二维码
        StringBuffer qrcode=new StringBuffer("");
        //协议版本 1Byte, Hex码 偶数代表业主，奇数代表访客
        qrcode.append(AppQrcodeProtocolVersionEnum.SECOND.getType());
        //用户类型 1Byte，Hex码。 暂定0x11表示物业管理员；
        qrcode.append(AppQrcodeUserTypeEnum.OWNER.getType());
        //用户UID 目前生成规则为用户手机号 不足6btye末尾补0
        qrcode.append(StringHandlerUtil.autlSupplyLast(12,phoneNum,"0"));
        //生成日期 格式 yyMMddHHmm
        qrcode.append(DateUtil.fomatDate(DateUtil.formatStringToDate(startTime,DateUtil.YYYYMMDDHHMM),DateUtil.YYMMDDHHMM));
        //流水号：1Byte，Hex码
        String cacheKey= RedisConstant.REDIS_APP_VISITOR_QRCODE_SERIAL_NUMBER_CACHE+userId+ DateUtil.fomatDate(new Date(), DateUtil.YYMMDD);
        Integer serialNumber=(Integer)redisServiceObject.getObject(cacheKey, Integer.class);
        if(serialNumber!=null){
            qrcode.append(StringHandlerUtil.autlSupply(2,Integer.toHexString(serialNumber).toUpperCase(),"0"));
        }else{
            serialNumber=1;
            qrcode.append(StringHandlerUtil.autlSupply(2,Integer.toHexString(serialNumber).toUpperCase(),"0"));
        }
        redisServiceObject.set(cacheKey, RedisConstant.REDIS_APP_VISITOR_QRCODE_SERIAL_NUMBER_CACHE_TIME, Integer.valueOf(serialNumber)+1);
        //有效时间 hex 码
        if(timeLimit==null) {
            qrcode.append("90");
        }else{
            qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(timeLimit / 10),"0").toUpperCase());
        }
        //有效次数 hex码
        qrcode.append("01");
        String identifier="";
        //电梯门禁标识 如有电梯和门禁权限时为0x03；只有电梯而无门禁权限时为0x01；只有门禁权限时为0x02
        if(StringUtils.isNotBlank(doorIds) && StringUtils.isNotBlank(elevatorUniques)){
            qrcode.append("03");
            identifier="03";
        }else if(StringUtils.isNotBlank(doorIds)){
            qrcode.append("02");
            identifier="02";
        }else if(StringUtils.isNotBlank(elevatorUniques)){
            qrcode.append("01");
            identifier="01";
        }else{
            qrcode.append("00");
            identifier="00";
        }
        if(!identifier.equals("00")) {
            //转换得到电梯及门禁数组
            String doors[] = StringHandlerUtil.splitString(doorIds);
            String floors[] = StringHandlerUtil.splitString(elevatorUniques);
            //门禁
            if(!identifier.equals("01")) {
                //门禁数量 HEX码
                qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(doors.length).toUpperCase(), "0"));
                //门禁机号 HEX码
                qrcode.append(StringHandlerUtil.assembleDeviceNum(doors));
            }
            //电梯
            if(!identifier.equals("02")) {
                Map<String,Set<String>> builds = new HashMap<>();
                //对电梯按照楼层权限权限分组
                for(String f : floors){
                    //电梯权限 HEX码
                    String floorNo = iPropertyVisitorPassCodeRecordDao.getFloorAuthByFloorNumAndDeviceUnique(floorNum, projectId + "1" + StringHandlerUtil.autlSupply(4,f,"0"));
                    if(StringUtils.isNotEmpty(floorNo)) {
                        boolean add = false;
                        for (String k : builds.keySet()) {
                            if (k.equals(floorNo)) {
                                Set<String> deviceUniques = builds.get(k);
                                deviceUniques.add(f);
                                add = true;
                            }
                        }
                        if (!add) {
                            Set<String> deviceUniques = new HashSet<>();
                            deviceUniques.add(f);
                            builds.put(floorNo, deviceUniques);
                        }
                    }
                }
                //有权限的电梯楼栋单元数量 最多8个单元 超过8个单元按拥有所有电梯权限处理
                qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(builds.keySet().size()).toUpperCase(), "0"));
                for(String floor : builds.keySet()){
                    //所属单元电梯数量 HEX 码
                    qrcode.append(StringHandlerUtil.autlSupply(2, Integer.toHexString(builds.get(floor).size()).toUpperCase(), "0"));
                    //所属单元电梯机号 HEX码
                    qrcode.append(StringHandlerUtil.assembleDeviceNum(builds.get(floor).toArray(new String[builds.get(floor).size()])));
                    result.put("floorNo",floorNum);
                    //设置有权限的楼层数量
                    qrcode.append("01");
                    //设置楼层号和直达楼层
                    qrcode.append(StringUtils.isBlank(floor) ? "00" : StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(floor)).toUpperCase(), "0"));
                    qrcode.append(StringUtils.isBlank(floor) ? "00" : StringHandlerUtil.autlSupply(2, Integer.toHexString(Integer.valueOf(floor)).toUpperCase(), "0"));
                }
            }
        }
        String value=qrcode.substring(16,32);
        //获取项目秘钥
        String projectKey=iPropertyVisitorPassCodeRecordDao.getQrcodeProjectKey(projectId);
        qrcode.append(DesEncryptUtil.ownerAndVisitorMacEncrypt(value, projectKey, qrcode.toString()));
        result.put("qrcode",qrcode);
        return result;
    }
}